I was stuck in implementing Simple Ftp with Winsock [migrated]

Posted by user67449 on Programmers See other posts from Programmers or by user67449
Published on 2012-10-11T07:05:29Z Indexed on 2012/10/11 9:52 UTC
Read the original article Hit count: 246

Filed under:

I want to implement a SimpleFtp with Winsock. But I was stuck in the maybe the file stream reading and writing. This is the Server.

#include <WinSock2.h>
#include <memory.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

#define MAX_FILE_NAME 100
#define DATA_PACK_SIZE 80*1000    // ??DataPack?????80KB
#define SOCKKET_BUFFER_SIZE 80*1000      // socket???
#define FILE_BUFFER_SIZE  DATA_PACK_SIZE-MAX_FILE_NAME-4*sizeof(int)-sizeof(u_long)      //?????,??,??????content?????
#define CONTENT_SIZE FILE_BUFFER_SIZE    // DataPack?????content???


// Define a structure to hold the content of a file
typedef struct FilePack{
    char fName[MAX_FILE_NAME];    // File's name
    int fLen;    // File's length
    int packNum;    // Number of the DataPack
    int packLen;    // DataPack's length
    int packCount;
    int contenLen;    // the content length the DataPack actually holds
    u_long index;    // ??????????
    char content[CONTENT_SIZE];    // DataPack??????
}DataPack, *pDataPack;

void WinsockInitial(){
    WSADATA wsaData;
    WORD wVersionRequested;
    int err;
    wVersionRequested=MAKEWORD(2,2);
    err=WSAStartup(wVersionRequested, &wsaData);
    if(err!=0){
        cout<<"Error at WSAStartup()."<<endl;
        exit(0);
    }

    if( LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2 ){
        cout<<"Error at version of Winsock. "<<endl;
        WSACleanup();
        exit(0);
    }
}

void SockBind(SOCKET sock, int port, sockaddr_in &addrsock){
    addrsock.sin_family=AF_INET;
    addrsock.sin_port=htons(port);
    addrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    if( bind(sock, (sockaddr*)&addrsock, sizeof(addrsock)) == SOCKET_ERROR ){
        cout<<"Error at bind(). Error: "<<GetLastError()<<endl;
        closesocket(sock);
        WSACleanup();
        exit(0);
    }
}

void SockListen(SOCKET sock, int bak){
    int err=listen(sock, bak);
    if(err==SOCKET_ERROR){
        cout<<"Error at listen()."<<WSAGetLastError()<<endl;
        closesocket(sock);
        WSACleanup();
        exit(0);
    }
}

int SockSend(DataPack &dataPack, SOCKET sock, char *sockBuf){
    int bytesLeft=0, bytesSend=0;
    int idx=0;

    bytesLeft=sizeof(dataPack);

    // ?DataPack?????sockBuf???
    memcpy(sockBuf, &dataPack, sizeof(dataPack));

    while(bytesLeft>0){
        bytesSend=send(sock, &sockBuf[idx], bytesLeft, 0);
        if(bytesSend==SOCKET_ERROR){
            cout<<"Error at send()."<<endl;
            return 1;
        }
        bytesLeft-=bytesSend;
        idx+=bytesSend;
    }
    return 0;
}



int GetFileLen(FILE *fp){
    // ??????
    if(fp==NULL){
        cout<<"Invalid argument. Error at GetFileLen()."<<endl;
        exit(0);
    }
    fseek(fp, 0, SEEK_END);
    int tempFileLen=ftell(fp);
    fseek(fp, 0, SEEK_SET);
    return tempFileLen;
}


int main(){

    int err;
    sockaddr_in addrServ;
    int port=8000;

    // Initialize Winsock
    WinsockInitial();

    // Create a socket
    SOCKET sockListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sockListen==INVALID_SOCKET){
        cout<<"Error at socket()."<<endl;
        WSACleanup();
        return 1;
    }

    // Bind the socket.
    SockBind(sockListen, port, addrServ);


    // Listen for incoming connection requests
    cout<<"Waiting for incoming connection requests..."<<endl;
    SockListen(sockListen, 5);

    // Accept the connection request.
    sockaddr_in addrClient;
    int len=sizeof(addrClient);
    SOCKET sockConn=accept(sockListen, (sockaddr*)&addrClient, &len);
    if(sockConn!=INVALID_SOCKET){
        cout<<"Connected to client successfully."<<endl;
    }

    // Set the buffer size of socket
    char sockBuf[SOCKKET_BUFFER_SIZE];
    int nBuf=SOCKKET_BUFFER_SIZE;
    int nBufLen=sizeof(nBuf);
    err=setsockopt(sockConn, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, nBufLen);
    if(err!=0){
        cout<<"Error at setsockopt(). Failed to set buffer size for socket."<<endl;
        exit(0);
    }

    //???????????
    err = getsockopt(sockConn, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, &nBufLen);
    if( SOCKKET_BUFFER_SIZE != nBuf){
        cout<<"Error at setsockopt(). ?socket????????"<<endl;
        closesocket(sockListen);
        closesocket(sockConn);
        WSACleanup();
        exit(0);
    }

    //------------------------------------------------------------------------//


    DataPack dataPackSend;
    memset(&dataPackSend, 0, sizeof(dataPackSend));


    int bytesRead;
    int bytesLeft;
    int bytesSend;
    int packCount;    // Counts how many DataPack needed



    FILE *frp;    // Used to read

    if(strcpy_s(dataPackSend.fName, "music.mp3")!=0){
        cout<<"Error at strcpy_s()."<<endl;
        return 1;
    }


    // Open the file in read+binary mode

    err=fopen_s(&frp, dataPackSend.fName, "rb");    
    if(err!=0){
        cout<<"Error at fopen_s()."<<endl;
        return 1;
    }

    char fileBuf[FILE_BUFFER_SIZE];

    // Set the buffer size of File
    if(setvbuf(frp, fileBuf, _IONBF, FILE_BUFFER_SIZE)!=0){
        cout<<"Error at setvbuf().Failed to set buffer size for file."<<endl;
        closesocket(sockListen);
        closesocket(sockConn);
        WSACleanup();
        exit(0);
    }

    // Get file's length
    int fileLen=GetFileLen(frp);
    cout<<"File ???:"<<fileLen<<" bytes."<<endl;


    // Calculate how many DataPacks needed
    packCount=ceil( (double)fileLen/CONTENT_SIZE );
    cout<<"File Length: "<<fileLen<<"    "<<"Content Size: "<<CONTENT_SIZE<<endl;
    cout<<"???"<<packCount<<" ?DataPack"<<endl;

    int i=0;

    for(i=0; i<packCount; i++){
        //?????dataPackSend?????
        memset(&dataPackSend, 0, sizeof(dataPackSend));

        // Fill the dataPackSend

        if(strcpy_s(dataPackSend.fName, "abc.txt")!=0){
            cout<<"Error at strcpy_s()."<<endl;
            return 1;
        }

        dataPackSend.packLen=DATA_PACK_SIZE;
        dataPackSend.fLen=fileLen;
        dataPackSend.packCount=packCount;


        if( packCount==1 ){       //??DataPack???

            bytesRead=fread(fileBuf, 1, dataPackSend.fLen, frp);

            dataPackSend.contenLen=dataPackSend.fLen;

            memcpy(dataPackSend.content, fileBuf, bytesRead);

            dataPackSend.packNum=0;    //???????DataPack

            // ?????dataPackSend?Client?
            if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
                cout<<"??? "<<dataPackSend.packNum<<" ?DataPack"<<endl;
            }

        }else if( packCount>1 && i<(packCount-1) ){    // ???(???????)    


            bytesRead=fread(fileBuf, 1, CONTENT_SIZE, frp);

            dataPackSend.contenLen=CONTENT_SIZE;

            memcpy(dataPackSend.content, fileBuf, bytesRead);

            dataPackSend.packNum=i;    

            //?dataPackSend??????Client?
            if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
                cout<<"??? "<<dataPackSend.packNum<<" ?DataPack."<<endl;
            }


        }else{    // ?????

            bytesRead=fread(fileBuf, 1, (dataPackSend.fLen-i*CONTENT_SIZE), frp);

            dataPackSend.contenLen=dataPackSend.fLen-i*CONTENT_SIZE;

            memcpy(dataPackSend.content, fileBuf, bytesRead);

            dataPackSend.packNum=i;

            //?dataPackSend???Client?
            if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
                cout<<"??? "<<dataPackSend.packNum<<" ?DataPack."<<endl;
            }

        }

    }

    fclose(frp);

    closesocket(sockListen);
    closesocket(sockConn);
    WSACleanup();
    return 0;
}

And this is Client.

    #include <WinSock2.h>
#include <memory.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

#define MAX_FILE_NAME 100
#define DATA_PACK_SIZE 80*1000    // ??DataPack?????80KB
#define SOCKKET_BUFFER_SIZE 80*1000      // socket???
#define FILE_BUFFER_SIZE  DATA_PACK_SIZE-MAX_FILE_NAME-4*sizeof(int)-sizeof(u_long)      //?????,??,??????content?????
#define CONTENT_SIZE FILE_BUFFER_SIZE    // DataPack?????content???


// Define a structure to hold the content of a file
typedef struct FilePack{
    char fName[MAX_FILE_NAME];    // File's name
    int fLen;    // File's length
    int packNum;    // Number of the DataPack
    int packLen;    // DataPack's length
    int packCount;    //DataPack???
    int contenLen;    // the content length the DataPack actually holds
    u_long index;    // ??????????
    char content[CONTENT_SIZE];    // DataPack??????
}DataPack, *pDataPack;

void WinsockInitial(){
    WSADATA wsaData;
    WORD wVersionRequested;
    int err;
    wVersionRequested=MAKEWORD(2,2);
    err=WSAStartup(wVersionRequested, &wsaData);
    if(err!=0){
        cout<<"Error at WSAStartup()."<<endl;
        exit(0);
    }

    if( LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2 ){
        cout<<"Error at version of Winsock. "<<endl;
        WSACleanup();
        exit(0);
    }
}

int SockRecv(SOCKET sock, char *sockBuf){
    int bytesLeft, bytesRecv;
    int idx=0;

    bytesLeft=DATA_PACK_SIZE;

    while(bytesLeft>0){
        bytesRecv=recv(sock, &sockBuf[idx], bytesLeft, 0);
        if(bytesRecv==SOCKET_ERROR){
            cout<<"Error at recv()."<<endl;
            return 1;
        }
        bytesLeft-=bytesRecv;
        idx+=bytesRecv;
    }
    return 0;
}

int main(){
    int err;
    sockaddr_in addrServ;
    int port=8000;

    // Initialize Winsock
    WinsockInitial();

    // Create a socket
    SOCKET sockClient=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sockClient==INVALID_SOCKET){
        cout<<"Error at socket()."<<endl;
        WSACleanup();
        return 1;
    }

    // Set the buffer size of socket
    char sockBuf[SOCKKET_BUFFER_SIZE];
    int nBuf=SOCKKET_BUFFER_SIZE;
    int nBufLen=sizeof(nBuf);
    err=setsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, nBufLen);
    if(err!=0){
        cout<<"Error at setsockopt(). Failed to set buffer size for socket."<<endl;
        exit(0);
    }

    //???????????
    err = getsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, &nBufLen);
    if( SOCKKET_BUFFER_SIZE != nBuf){
        cout<<"Error at getsockopt(). ?socket????????"<<endl;
        closesocket(sockClient);
        WSACleanup();
        exit(0);
    }

    // Connect to the Server
    addrServ.sin_family=AF_INET;
    addrServ.sin_port=htons(port);
    addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    err=connect(sockClient, (sockaddr*)&addrServ, sizeof(sockaddr));
    if(err==SOCKET_ERROR){
        cout<<"Error at connect()."<<GetLastError()<<endl;
        closesocket(sockClient);
        WSACleanup();
        return 1;
    }else{
        cout<<"Connected to the FTP Server successfully."<<endl;
    }


/*
    int i=0;
    int bytesRecv, bytesLeft, bytesWrite;
    int packCount=0, fLen=0; 

    DataPack dataPackRecv;

    //??????
    SockRecv(sockClient, sockBuf);

    memcpy(&dataPackRecv, sockBuf, sizeof(dataPackRecv));

    cout<<"???? "<<dataPackRecv.packNum<<" ?DataPack."<<endl;
    cout<<"?DataPack??fName????: "<<dataPackRecv.fName<<endl;

    //???????
    packCount=dataPackRecv.packCount;
    cout<<"?? "<<packCount<<" ?DataPack."<<endl;

    fLen=dataPackRecv.fLen;


    // Create a local file to write into
    FILE *fwp;

    err=fopen_s(&fwp, dataPackRecv.fName, "wb");
    if(err!=0){
        cout<<"Error at creat fopen_s(). Failed to create a local file to write into."<<endl;
        return 1;
    }

    // Set the buffer size of File
    char fileBuf[FILE_BUFFER_SIZE];

    if(setvbuf(fwp, fileBuf, _IONBF, FILE_BUFFER_SIZE)!=0){
        cout<<"Error at setvbuf().Failed to set buffer size for file."<<endl;
        memset(fileBuf, 0, sizeof(fileBuf));
        closesocket(sockClient);
        WSACleanup();
        exit(0);
    }

    //???????content????
    memcpy(fileBuf, dataPackRecv.content, sizeof(dataPackRecv.content));
    bytesWrite=fwrite(fileBuf, 1, sizeof(fileBuf), fwp);
    if(bytesWrite<sizeof(fileBuf)){
        cout<<"Error at fwrite(). Failed to write the content of dataPackRecv to local file."<<endl;
    }

    //?????packCount-1?????????????????
    for(int i=1; i<packCount; i++){

        // ?????????
        memset(sockBuf, 0, sizeof(sockBuf));
        memset(&dataPackRecv, 0, sizeof(dataPackRecv));
        memset(fileBuf, 0, sizeof(fileBuf));

        SockRecv(sockClient, sockBuf);
        memcpy(&dataPackRecv, sockBuf, sizeof(dataPackRecv));

        cout<<"???? "<<dataPackRecv.packNum<<" ?DataPack."<<endl;

        //????
        memcpy(fileBuf, dataPackRecv.content, dataPackRecv.contenLen);

        bytesWrite=fwrite(fileBuf, 1, dataPackRecv.contenLen, fwp);
        if(bytesWrite<dataPackRecv.contenLen){
            cout<<"Error at fwrite(). Failed to write the content of dataPackRecv to local file."<<endl;
        }
    }

    if( (i+1)==packCount ){
        cout<<"??DataPack????????!"<<endl;
    }
    fclose(fwp);
    closesocket(sockClient);
    WSACleanup();
    return 0;*/
}

© Programmers or respective owner

Related posts about c++